library(readxl)
library(tidyverse)
library(httr)
library(pander)
library(sf)
library(dplyr)
library(stringr)
library(rnaturalearth)
library(rnaturalearthdata)
library(leaflet)
library(RColorBrewer)
library(xts)
library(dygraphs)
library(scales)
# This makes data loading easier
load_excel_from_url <- function(url) {
temp_xlsx <- tempfile(fileext = ".xlsx")
h <- handle(url)
GET(
url,
handle = h,
write_disk(temp_xlsx, overwrite = TRUE),
user_agent("R httr")
)
stopifnot(file.exists(temp_xlsx))
read_xlsx(temp_xlsx, skip = 6)
}
# Get arrest data
arrests <- load_excel_from_url(
"https://ucla.app.box.com/index.php?rm=box_download_shared_file&shared_name=9d8qnnduhus4bd5mwqt7l95kz34fic2v&file_id=f_1998578415974"
)
# Clean up the missing
arrests <- arrests %>%
mutate(
`Apprehension AOR` = if_else(
is.na(`Apprehension AOR`),
"HQ Area of Responsibility",
`Apprehension AOR`
)
)
# Get deportation data
deportations <- load_excel_from_url(
"https://ucla.app.box.com/index.php?rm=box_download_shared_file&shared_name=9d8qnnduhus4bd5mwqt7l95kz34fic2v&file_id=f_1998579549029"
)
# Get map of Areas
# Download & unzip the shapefile for the AORs
zip_url <- "https://github.com/deportationdata/ice/raw/refs/heads/main/data/ice-aor-shp.zip"
tmp <- tempfile(fileext = ".zip")
download.file(zip_url, tmp, quiet = TRUE) # suppress download messages
unzip(tmp, exdir = "ice_aor", overwrite = TRUE)
# Read shapefile silently
aor_sf <- suppressMessages(st_read("ice_aor/ice-aor-shp.shp", quiet = TRUE))
# Transform CRS to WGS 84 (EPSG:4326) for Leaflet
aor_sf <- st_transform(aor_sf, 4326)The U.S. Immigration and Customs Enforcement (ICE) agency enforces federal immigration laws through arrests, detentions, and deportations. In recent years, ICE has faced accusations of overreach and abuse of power, including reports of wrongful detentions and deportations. This analysis approaches these topics neutrally, focusing on empirical patterns in enforcement activity rather than policy judgment.
Using publicly available ICE data obtained from the Deportation Data Project, this report examines arrests and deportations across the United States, organized by Area of Responsibility (AOR), the regional offices responsible for specific geographic areas. The analysis includes national and regional trends over time, the criminal history of deportees, instances of deportations to countries other than the individual’s citizenship or birth country, and the distribution of deportees by nationality.
# Summarize deportations
dep_aor <- deportations %>%
group_by(`Docket AOR`) %>%
summarise(Count_deport = n(), .groups = "drop") %>%
dplyr::rename(aor_nam = `Docket AOR`) %>%
mutate(
aor_nam = str_remove(aor_nam, " Area of Responsibility$"),
aor_nam = str_replace(aor_nam, "^St\\. Paul$", "St Paul")
)
# Summarize arrests
arrest_aor <- arrests %>%
dplyr::rename(`Docket AOR` = `Apprehension AOR`) %>%
group_by(`Docket AOR`) %>%
summarise(Count_arrest = n(), .groups = "drop") %>%
dplyr::rename(aor_nam = `Docket AOR`) %>%
mutate(
aor_nam = str_remove(aor_nam, " Area of Responsibility$"),
aor_nam = str_replace(aor_nam, "^St\\. Paul$", "St Paul")
)
# Join counts
aor_sf <- aor_sf %>%
left_join(dep_aor, by = "aor_nam") %>%
left_join(arrest_aor, by = "aor_nam") %>%
mutate(
Count_deport = ifelse(is.na(Count_deport), 0, Count_deport),
Count_arrest = ifelse(is.na(Count_arrest), 0, Count_arrest)
)
# Define color palettes
pal_deport <- colorNumeric(
palette = colorRamp(c("#ffcccc", "#990000")), # light red to dark red
domain = aor_sf$Count_deport,
na.color = "#cccccc"
)
pal_arrest <- colorNumeric(
palette = colorRamp(c("#ffcccc", "#990000")),
domain = aor_sf$Count_arrest,
na.color = "#cccccc"
)
# Leaflet map
leaflet(aor_sf) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(lng = -98.5795, lat = 39.8283, zoom = 4) %>%
# Deportation polygons
addPolygons(
fillColor = ~pal_deport(Count_deport),
weight = 0.5,
color = "white",
fillOpacity = 0.8,
group = "Deportations",
highlightOptions = highlightOptions(
weight = 2,
color = "#666",
fillOpacity = 0.9,
bringToFront = TRUE
),
label = ~paste0(
"<strong>", aor_nam, "</strong><br/>",
"Deportations: ", Count_deport, "<br/>",
"Arrests: ", Count_arrest
) %>% lapply(htmltools::HTML)
) %>%
# Arrest polygons
addPolygons(
fillColor = ~pal_arrest(Count_arrest),
weight = 0.5,
color = "white",
fillOpacity = 0.8,
group = "Arrests",
highlightOptions = highlightOptions(
weight = 2,
color = "#666",
fillOpacity = 0.9,
bringToFront = TRUE
),
label = ~paste0(
"<strong>", aor_nam, "</strong><br/>",
"Deportations: ", Count_deport, "<br/>",
"Arrests: ", Count_arrest
) %>% lapply(htmltools::HTML)
) %>%
# Layer control to toggle
addLayersControl(
baseGroups = c("Deportations", "Arrests"),
options = layersControlOptions(collapsed = FALSE)
)